package com.megalith.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import com.megalith.constant.ResultCode;
import com.megalith.dto.CandidateProcessDTO;
import com.megalith.dto.CandidateProcessInstanceBaseDTO;
import com.megalith.dto.CandidateProcessInstanceDTO;
import com.megalith.service.CandidateTaskService;
import com.megalith.vo.*;
import lombok.extern.slf4j.Slf4j;
import org.flowable.engine.HistoryService;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.TaskService;
import org.flowable.engine.history.HistoricActivityInstance;
import org.flowable.engine.history.HistoricDetail;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.task.api.Task;
import org.flowable.task.api.history.HistoricTaskInstance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Description TODO
 * @Author lfp
 * @Date 2022/7/16
 * @Version 1.0
 */
@Service
@Slf4j
public class CandidateTaskServiceImpl implements CandidateTaskService {

    @Autowired
    private RuntimeService runtimeService;

    @Autowired
    private TaskService taskService;

    @Autowired
    private HistoryService historyService;

    @Override
    public Result startCandidateProcess(CandidateProcessDTO candidateProcessDTO) {
        Map<String, Object> variables = new HashMap<>();
        variables.put("staff",candidateProcessDTO.getStaff());
        variables.put("days",candidateProcessDTO.getDays());

        //根据候选人流程定义key，并传入全局流程变量staff，来启动候选人流程
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(candidateProcessDTO.getProcessDefinitionKey(),variables);
        if(processInstance != null){
            return Result.ok(processInstance.getId(),ResultCode.SYS_SUCCESS.getDes());
        }else {
            return Result.sysError(ResultCode.SYS_ERROR.getDes());
        }
    }

    @Override
    public Result completePersonalProcess(CandidateProcessInstanceDTO processInstanceDTO) {
        //根据流程实例编号、处理人，查询任务
        Task task = taskService.createTaskQuery()
                .processInstanceId(processInstanceDTO.getProcessInstanceId())
                .taskAssignee(processInstanceDTO.getAssignee())
                .active()
                .singleResult();

        if(task != null){
            //如果是staffTask 则必须设置 managerTask的部门经理候选人
            if("staffTask".equals(task.getTaskDefinitionKey())){
                if(hasCandidate(processInstanceDTO.getManagerCandidate(),"manager")){

                    Map<String, Object> param = new HashMap<>();
                    List<Map<String, Object>> candidateList = processInstanceDTO.getManagerCandidate();
                    for (int i = 0; i < candidateList.size(); i++) {
                        param.put("manager"+(i+1),candidateList.get(i).get("manager"));
                    }

                    taskService.complete(task.getId(),param);
                    return Result.ok();
                }else{
                    return Result.sysError("managerCandidate部门经理候选人不能为空");
                }
            }

            //如果是managerTask 或者是 generalManagerTask 总经理审批，则必须设置人力资源humanResourcesTask候选人
            if("managerTask".equals(task.getTaskDefinitionKey()) ||
                    "generalManagerTask".equals(task.getTaskDefinitionKey())){
                if(hasCandidate(processInstanceDTO.getHumanResourcesCandidate(),"humanResources")){

                    Map<String, Object> param = new HashMap<>();
                    List<Map<String, Object>> candidateList = processInstanceDTO.getHumanResourcesCandidate();
                    for (int i = 0; i < candidateList.size(); i++) {
                        param.put("humanResources"+(i+1),candidateList.get(i).get("humanResources"));
                    }

                    param.put("generalManager","caozong");//硬编码流程变量

                    taskService.complete(task.getId(),param);
                    return Result.ok();
                }else{
                    return Result.sysError("humanResourcesCandidate人力资源侯选人不能为空");
                }
            }
            taskService.complete(task.getId());
            return Result.ok();
        }
        return Result.ok();
    }


    @Override
    public Result claimCandidateTask(CandidateProcessInstanceBaseDTO processInstanceBaseDTO) {
        Task task = taskService.createTaskQuery()
                .taskCandidateUser(processInstanceBaseDTO.getAssignee())
                .processInstanceId(processInstanceBaseDTO.getProcessInstanceId())
                .active()
                .singleResult();

        if(task != null){
            taskService.claim(task.getId(),processInstanceBaseDTO.getAssignee());
            return Result.ok("任务领取成功");
        }else {
            return Result.error(ResultCode.SYS_ERROR.getDes());
        }
    }

    @Override
    public Result unclaimCandidateTask(CandidateProcessInstanceBaseDTO processInstanceBaseDTO) {
        Task task = taskService.createTaskQuery()
                .taskCandidateUser(processInstanceBaseDTO.getAssignee())
                .processInstanceId(processInstanceBaseDTO.getProcessInstanceId())
                .active()
                .singleResult();

        if(task != null){
            taskService.unclaim(task.getId());
            return Result.ok("任务归还成功");
        }else {
            return Result.error(ResultCode.SYS_ERROR.getDes());
        }
    }


    /**
    *@Description 判断候选人集合
    *@Author lfp
    *@param candidateList
    *@param key
    *@Return
    */
    public boolean hasCandidate(List<Map<String,Object>> candidateList,String key){
        boolean tag = false;

        if(candidateList.size() >0){
            for (int i = 0; i < candidateList.size(); i++) {
                Map<String, Object> item = candidateList.get(i);
                if(item.containsKey(key) && item.get(key) != null){
                    tag = true;
                    break;
                }
            }

        }
        return tag;
    }

}
